#include <stdio.h>
#include <ccmd/cmd.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>


struct result {
    char *name;
    char *address;
    uint32_t age;
    bool fresh;
};


/* 定义 --help 的解析函数 */
static int opt_help_parser(void *opts, char *option, char *arg) 
{
    (void)opts;
    (void)option;
    (void)arg;

    usage();
    exit(EXIT_SUCCESS); // 执行完直接退出
}

/*选项解析函数*/
static int opt_default_parser(void *opts, char *option, char *arg) 
{
    if (!opts || !option) {
        return -1;
    }

    char *eptr = NULL;
    struct result *ptr_result = (struct result *)opts;
    if (0 == strcmp(option, "name")) {
        ptr_result->name = arg;
    } else if (0 == strcmp(option, "age")) {
        ptr_result->age = strtol(arg, &eptr, 0);
        if (eptr && *eptr != '\0')
        {
            printf("Parse option %s %s error\r\n", option, arg);
            return -1;
        }

        if (ptr_result->age < 6 || ptr_result->age > 35)
        {
            printf("Invalid age(%s) for strduent, valid range(6-35)\r\n", arg);
            return -1;
        }
    } else if (0 == strcmp(option, "address")) {
        ptr_result->address = arg;
    }else if (0 == strcmp(option, "fresh")) {
        ptr_result->fresh = true;
    } else {
        printf("Unknow option %s\r\n", option);
        return -1;
    }

    return 0;
}


/*  定义命令行选项 */
static void opts_register(void)
{
#define INIT_OPTION(n, fn, req, help_str) {\
    cmd_opt_cfg cfg; \
    cfg.name = n;\
    cfg.help = help_str;\
    cfg.help_fn = NULL;\
    cfg.parser_fn = (cmd_opt_parser)fn;\
    struct option opt_cfg;\
    opt_cfg.name = n;\
    opt_cfg.has_arg = req;\
    opt_cfg.flag = 0;\
    opt_cfg.val = 0;\
    add_cmd_opt(&cfg, &opt_cfg);\
}
    INIT_OPTION("help", opt_help_parser, no_argument, " --help: prints this help\n");
    INIT_OPTION("name", opt_default_parser, required_argument, " --name: specify student name\n");
    INIT_OPTION("address", opt_default_parser, required_argument, " --address: specify student home address\n");
    INIT_OPTION("age", opt_default_parser, required_argument, " --age: specify student age\n");
    INIT_OPTION("fresh", opt_default_parser, no_argument, " --fresh: is fresh graduate\n");
}

static void cmd_log(uint32_t level, const char *msg)
{
    printf("[level %d]%s", level, msg);
}


void main(const int argc, const char **argv)
{
    //set_cmd_log_printer(cmd_log);


    opts_register();
    struct result command_results={0};

    
    int ret = cmd_parse((void *)&command_results, argc, argv);
    if (0 != ret)
    {
        return;
    }


    printf("get student info:\r\n");
    printf(" name   : %s\r\n", command_results.name);
    printf(" address: %s\r\n", command_results.address);
    printf(" age    : %d\r\n", command_results.age);
    printf(" fresh  : %s\r\n", command_results.fresh?"true":"false");

    return;
}

/*

cd example
mkdir build && cd build
cmake ..
make


root@keep-VirtualBox:/media/sf_VM_SHARE/ccmd/example/build# ./ccmd_test --help
Usage
 ./ccmd_test [options] ...
Options:
 --help: prints this help
 --name: specify student name
 --address: specify student home address
 --age: specify student age
 --fresh: is fresh graduate



root@keep-VirtualBox:/media/sf_VM_SHARE/ccmd/example/build# ./ccmd_test --name xiaoming --address Fuzhou,Fujian --age 18 --fresh
get student info:
 name   : xiaoming
 address: Fuzhou,Fujian
 age    : 18
 fresh  : true



*/